home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Software Vault: The Gold Collection
/
Software Vault - The Gold Collection (American Databankers) (1993).ISO
/
cdr22
/
ctest259.zip
/
CCNEW.ASM
< prev
next >
Wrap
Assembly Source File
|
1993-06-07
|
41KB
|
740 lines
PAGE ,120
.386p ; 80386 code will be used
.387 ; need coprocessor, too
JMPS EQU <JMP SHORT> ; declare jumps as short
JES EQU <JE SHORT> ; since near jumps (+/- 32K)
JBS EQU <JB SHORT> ; are default in 386 mode
JNZS EQU <JNZ SHORT> ; and these cannot execute
JCS EQU <JC SHORT> ; on the older CPUs
JZS EQU <JZ SHORT>
JNES EQU <JNE SHORT>
JAES EQU <JAE SHORT>
JBES EQU <JBE SHORT>
JAS EQU <JA SHORT>
cpu_i8088 EQU 1
cpu_i8086 EQU 2
cpu_V20 EQU 3
cpu_V30 EQU 4
cpu_i188 EQU 5
cpu_i186 EQU 6
cpu_i286 EQU 7
cpu_i386 EQU 8
cpu_i386sx EQU 9
cpu_ct38600 EQU 10
cpu_ct38600sx EQU 11
cpu_486dlc EQU 12
cpu_486slc EQU 13
cpu_RapidCAD EQU 14
cpu_i486 EQU 15
cpu_i486SX EQU 16
cpu_pentium EQU 17
ndp_NoCopro EQU 0
ndp_Emul EQU 1
ndp_i8087 EQU 2
ndp_i80C187 EQU 3
ndp_i80287 EQU 4
ndp_i287XL EQU 5
ndp_i387 EQU 6
ndp_i387sx EQU 7
ndp_2C87 EQU 8
ndp_3C87 EQU 10
ndp_3C87sx EQU 11
ndp_82S87 EQU 12
ndp_83D87 EQU 14
ndp_83S87 EQU 15
ndp_83C87 EQU 16
ndp_83C87s EQU 17
ndp_38700 EQU 18
ndp_38700sx EQU 19
ndp_i387DX EQU 20
ndp_RapidCAD EQU 21
ndp_i486 EQU 22
ndp_82S87p EQU 23
ndp_387plus EQU 25
ndp_83S87p EQU 26
ndp_emc87 EQU 27
ndp_pentium EQU 28
STRT_TIM MACRO
MOV AL, 0B4h ; timer 2 is
OUT 43h, AL ; programmed as a rate generator
XOR AL, AL ; load zero
OUT 42h, AL ; reset
OUT 42h, AL ; timer 2
ENDM
STOP_TIM MACRO
MOV AL, 80h ; timer 2
OUT 43h, AL ; immediately latched
IN AL, 42h ; read LSB
MOV BL, AL ; save LSB
IN AL, 42h ; read MSB
MOV BH, AL ; save MSB
NEG BX ; negate for timer count
ENDM
CODE SEGMENT BYTE USE16 PUBLIC 'CODE'
ASSUME CS:CODE
PUBLIC SpeedTest
; declare parameters
Debug_Flag EQU [BP+24] ; <> 0, if debugging output desired
Ext_Flag EQU [BP+22] ; zero, if no extended memory
EMS_Flag EQU [BP+20] ; zero, if no expanded memory
BufferPtr EQU [BP+16] ; buffer for EMS u. EXT test
EMS_Base EQU [BP+12] ; address of EMS-frame
ScreenPtr EQU [BP+8] ; start address of video memory
ResultPtr EQU [BP+4] ; pointer to result struct
; declare local variables
Stat EQU [BP-2] ; mem for 80x87 status word
Ctrl EQU [BP-4] ; mem for 80x87 control word
GDT EQU [BP-52] ; mem for global descriptor table
SystemStat EQU [BP-53] ; mem for system status
SaveCtrl EQU [BP-55] ; original 80x87 control word
; declare result record
CPU_NDP_TYP EQU [SI]
AAMTime EQU [SI+2]
MovEvenTime EQU [SI+6]
BIOSWrTime EQU [SI+8]
MovByteTime EQU [SI+10]
MovEMSTime EQU [SI+12]
MovExtTime EQU [SI+14]
ScrFillTime EQU [SI+16]
Dummy2 EQU [SI+18]
i87Time EQU [SI+20]
i287Time EQU [SI+22]
MovDblTime EQU [SI+24]
SpeedTest PROC NEAR
PUSH BP ; save caller's frame pointer
MOV BP, SP ; make new frame pointer
SUB SP, 55 ; alloc mem for local variables
PUSH DS ; save Turbo Pascal's data segment
PUSHF ; save original flag setting
$inittimer: CLI ; disable interrupts
CLD ; auto increment for string operations
IN AL, 61h ; port B - system control
MOV [SystemStat], AL ; save system status
AND AL, 11111101b ; clear speaker bit (disable speaker)
OR AL, 1 ; turn on bit for timer 2 (enable it)
CMP AL, [SystemStat] ; system already configured correctly ?
JES $aam ; no need to configure it
OUT 61h, AL ; reconfigure system (tmr 2 on,spk off)
$aam: CMP WORD PTR Debug_Flag,0; debugging output desired ?
JNZS $aam1 ; no
MOV AH, 9 ; #9, print string
PUSH CS ; load
POP DS ; address of
MOV DX, OFFSET CS:$dbg2 ; debugging message
INT 21h ; call DOS, print debugging message
JMPS $aam1 ; skip message text
$dbg2 DB 'About to perform AAM speed test', 0Dh, 0Ah ,'$'
$aam1: STRT_TIM ; start timer 2
REPT 200
AAM ; execute 200 AAMs
ENDM
STOP_TIM ; elapsed time of timer 2 in BX
LDS SI, ResultPtr ; pointer to result struct
MOV [AAMTime], BX ; save time for AAMs
$begin_test:CMP WORD PTR Debug_Flag,0; debugging output desired ?
JNZS $cpu_ndptst ; nope
MOV AH, 9 ; #9, print string
PUSH CS ; load
POP DS ; address of
MOV DX, OFFSET CS:$dbg1 ; debugging message
INT 21h ; call DOS, print debugging message
JMPS $cpu_ndptst ; skip message text
$dbg1 DB 'About to perform CPU and NDP test', 0Dh, 0Ah ,'$'
$cpu_ndptst:LDS SI, ResultPtr ; pointer to result struct
FNSTCW [SaveCtrl] ; save original NDP ctrl word
PUSH SP ; test updating
POP AX ; of stackpointer
CMP AX, SP ; stackpointer updated before push ?
JES $286_386 ; no, must be 286, 386 or 486
MOV AX, 1 ; try to shift
MOV CL, 33 ; accu 33 times
SHL AX, CL ; shift count masked off ?
JNZS $186_188 ; yes, must be 186 or 188
PUSHA ; PUSHA executed on 88/86 as JMP $+2
STC ; carry set if V20 or V30
JCS $V20_V30 ; yes, must be V20 or V30
PUSHF ; save flags
POP AX ; pop flags into AX
AND AH, 00FH ; clear bits 12-15 of flag register
PUSH AX ; put new flags in stack
POPF ; pop into flag register
PUSHF ; put flags on stack
POP AX ; get flags
AND AH, 0F0H ; test if all bits
CMP AH, 0F0H ; in highest nibble set
JES $88_86 ; all bits in highest nibble set
XOR DL, DL ; failed all tests, unknown CPU
JMPS $copro_test ; go and test NDP
$88_86: MOV DL, cpu_i8088 ; else it's an 88 or 86
JMPS $queue_test ; decide wether 88 or 86
$V20_V30: POPA ; remove pushed bytes
MOV DL, cpu_V20 ; it's an V20 or V30
JMPS $queue_test ; decide wether V20 or V30
$186_188: MOV DL, cpu_i188 ; 188/186
$queue_test:LEA BX, [$patch] ; load patch address into BX
MOV BYTE PTR CS:[BX], 42h; preset with opcode for INC DX
MOV AL, 90H ; patch in a NOP (opcode 90h)
MOV CL, 31 ; rotate register 31 times to use up
ROL AH, CL ; time so prefetch queue can be filled
MOV BYTE PTR CS:[BX], AL ; insert NOP at label $patch
NOP ; fill
NOP ; prefetch
NOP ; queue
NOP ; with NOPs
$patch: INC DX ; patched to NOP on i88, i188 and V20
$copro_test:JMP $ndp_test ; check for coprocessor
$286_386: MOV DL, cpu_i286 ; 286, 386 or 486
PUSH 7000h ; try to set
POPF ; IOPL and NT fields
PUSHF ; in bit 12-14
POP AX ; of flag register
TEST AX, 7000h ; bits cannot be set in 286 real mode
JZS $copro_test ; bits not set --> 286
INC DX ; CPU is an 386 (DL = 8) or 486
MOV EBX, ESP ; save current stackpointer to align it
AND ESP, 0FFFFFFFCh ; align stack to avoid AC fault
PUSHFD ; save EFLAGS
POP EAX ; get EFLAGS from stack
MOV ECX, EAX ; original value of EFLAGS
XOR EAX, 40000H ; toggle AC bit in EFLAGS
PUSH EAX ; copy new value
POPFD ; to EFLAGS
PUSHFD ; get new EFLAGS value
POP EAX ; put into EAX
XOR EAX, ECX ; test if AC bit could be changed
PUSH ECX ; restore original
POPFD ; value of EFLAGS
MOV ESP, EBX ; restore original stack pointer
OR EAX, EAX ; EAX = 0 on 386, 40000h on 486
JNZS $486_486dlc ; if <> 0, must be 486/486dlc/486slc
$chk_38600: PUSH DX ; save CPU code
MOV ESI, 32 ; 32 trials to check for POPAD bug
MOV EAX, 12345678 ; load some value
$trial_loop:MOV EBX, EAX ; save value for comparison
MOV EDX, 0 ; prepare index and
MOV EDI, 0 ; base register to point to DS:0
PUSHAD ; push all 32-bit registers
POPAD ; pop all 32-bit registers
MOV ECX, [EDX+EDI] ; mem access changes EAX (POPAD bug!)
CMP EAX, EBX ; EAX changed ?
JNZS $changed ; EAX changed -> bug in AMD/Intel 386
ROL EAX, 1 ; try next number
DEC ESI ; decrement trial counter
JNZS $trial_loop ; until 32 trials thru, exits with Z=1
$changed: POP DX ; restore CPU code
JNZS $copro_test ; EAX changed, must be Intel/AMD 386
MOV DL, cpu_ct38600 ; C&T 38600 doesn't have that bug
JMPS $copro_test ; now test for coprocessor
$486_486dlc:MOV AX, 0FFFFh ; load initial multiplicand
MOV BX, 0FFFFh ; load multiplicator
STRT_TIM ; start timer 2
REPT 30 ; 486: MUL takes 26, AAM 15 clocks
MUL BX ; execute 30 MULs
ENDM ; 486DLC: MUL takes 3, AAM 17 clocks
STOP_TIM ; elapsed time of timer 2 in BX
SHL BX, 3 ; time for 240 MULs
CMP BX, [AAMTime] ; time for 240 MULs>time for 200 AAMs ?
MOV DL, cpu_i486 ; default: it's a 486 (CPU = 15)
JAS $ndp_test ; yes, 486 has slow MUL
ADD BX, BX ; time for 480 MULs
CMP BX, [AAMTime] ; time for 480 MULs>time for 200 AAMs ?
JAS $pentium ; yes, Pentium MUL takes 11 clocks
MOV DL, cpu_486dlc ; no, fast MUL -> 486DLC/486SLC
JMPS $ndp_test ; continue with NDP test
$pentium: MOV DL, cpu_pentium ; speed of Pentium between 486DLC..486
$ndp_test: XOR DH, DH ; assume no coprocessor
XOR AX, AX ; clear register
OUT 0F0h, AL ; clear error signal of coprocessor
FNINIT ; initialize coprocessor
MOV [Ctrl], AX ; clear status variable
NOT AX ; load all 1's
MOV [Stat], AX ; initialize status variable to all 1's
FNSTCW [Ctrl] ; store NDP control word
MOV AX, [Ctrl] ; get control word
AND AX, 0F3Fh ; extract RC, PC and exception masks
CMP AX, 033Fh ; RC=0, PC=3, masks=3F ?
JNES $chk_486sx ; no -> no coprocessor present
FNSTSW [Stat] ; store NDP status
TEST WORD PTR [Stat],383Fh; stack top & exceptions must be clear
JNZS $chk_486sx ; ST & exceptions not clear -> no NDP
MOV DH, ndp_Emul ; coprocessor is at least emulator (=1)
CMP DL, cpu_i286 ; is CPU 80286 or higher ?
JBS $no_emulat ; no, emulation impossible
SMSW AX ; get machine status word
TEST AL, 4 ; test if EM bit of MSW set
JZS $no_emulat ; not set -> no NDP emulation
$chk_486sx: CMP DL, cpu_i486 ; CPU = Intel 486 and no/emulated copro ?
SBB DL, -1 ; yes, CPU is 486sx (increment DL)
JMP $ndp_exit ; no further NDP checking
$no_emulat: MOV DH, ndp_i8087 ; coprocessor is at least 8087 (=2)
FLD1 ; load 1.0
WAIT ; needed for 8087
FLDZ ; load 0.0
WAIT ; needed for 8087
FDIV ; 1.0 / 0.0 = +infinity
WAIT ; needed for 8087
FLD ST(0) ; duplicate +infinity
WAIT ; needed for 8087
FCHS ; generate -infinity
WAIT ; needed for 8087
FCOMPP ; compare infinities and clear NDP stk
WAIT ; needed for 8087
FSTSW WORD PTR [Stat] ; save condition codes
MOV AX, [Stat] ; load condition codes
SAHF ; transfer into CPU flags
JNES $187_387 ; 187, C287 or 387 if numbers not equal
CMP DL, cpu_i286 ; is CPU >= 286 ?
JBS $ndp_exit1 ; no, coprocessor is 8087
MOV DH, ndp_i80287 ; coprocessor is 287
JMPS $chk_iit ; check for IIT coprocessors
$187_387: CMP DL, cpu_i286 ; is CPU >= 286 ?
JAES $C287_387 ; yes, NDP is either C287, 287XL or 387
MOV DH, ndp_i80C187 ; coprocessor is 187
JMPS $ndp_exit1 ; store CPU and NDP code
$C287_387: CMP DL, cpu_i386 ; is CPU >= 386 ?
JAES $387_486 ; yes, NDP is 387 or 387sx, 486
MOV DH, ndp_i287XL ; coprocessor is C287
JMPS $chk_iit ; check for IIT coprocessors
$387_486: CMP DL, cpu_i486 ; is CPU >= 486 ?
JAES $i486 ; yes, NDP is 486 / 487
MOV DH, ndp_i387 ; coprocessor is 387 or 387sx
JMPS $chk_iit ; check for IIT coprocessors
$i486: CMP DL, cpu_pentium ; is CPU Intel Pentium ?
JES $ipentium ; yes, FPU is also Pentium
MOV DH, ndp_i486 ; NDP = 486 / 487
JMP $ndp_exit ; done with FPU detection
$ipentium: MOV DH, ndp_pentium ; set FPU type = Pentium
$ndp_exit1: JMP $ndp_exit ; no further tests required
$chk_iit: FNINIT ; initialize coprocessor
FLD CS:[$denormal] ; load denormal number
FADD ST(0), ST ; result is zero on IIT
FNSTSW AX ; get status of NDP into AX
TEST AL, 02h ; test if denormal exception flag set
JNZS $chk_ulsi ; Intel NDPs signal denormal exception
ADD DH,ndp_2c87-ndp_i80287;set IIT coprocessor types
JMPS $ndp_exit1 ; coprocessor type found
$chk_ulsi: CMP DL, cpu_i386 ; CPU >= 386 ?
JBS $chk_cyrix1 ; no, can not be ULSI
FNINIT ; initialize coprocessor
FLDCW CS:[$53bit_prec] ; PC => 53 bits (ULSI ignores PC)
FLD TBYTE PTR CS:[$op1] ; load 2-epsilon
FLD1 ; load 1
FADDP ST(1), ST ; result should be 3 and PE raised
FSTP TBYTE PTR [GDT] ; store result, clear NDP stack
FNSTSW AX ; get coprocessor status word
TEST AL, 20h ; precision exception ?
JNZS $chk_cyrix1 ; ULSI computes 64 bit result, no PE!
FWAIT ; make sure result is stored
CMP BYTE PTR [GDT], 0F8h ; check least significant mantissa bits
JNES $chk_cyrix1 ; not expected result for ULSI
CMP BYTE PTR [GDT+9], 40h; check exponent hi-byte
JNES $chk_cyrix1 ; not expected result for ULSI
ADD DH,ndp_83C87-ndp_i387; set ULSI types
JMPS $ndp_exit1 ; done
$chk_cyrix1:FNINIT ; initialize coprocessor
FLD TBYTE PTR CS:[$nan] ; load positive NaN
FLD ST(0) ; duplicate NaN
FCHS ; make negative NaN
FPATAN ; ATAN (-NaN, +NaN) should return +NaN
FSTP TBYTE PTR [GDT] ; store result, clear NDP stack
FWAIT ; wait until result is stored
CMP BYTE PTR [GDT+9], 7Fh; Cyrix ret. +NAN (7F),Intel -NAN (FF)
JNES $chk_ct ; Intel coprocessor
$chk_emc87: FNSTCW [Ctrl] ; store control word
OR BYTE PTR [Ctrl+1],80h; set msb of control word
FLDCW [Ctrl] ; and load back into coprocessor
FSTCW [Ctrl] ; store control word again
FWAIT ; wait until stored
TEST BYTE PTR [Ctrl+1],80h; could msb be set ?
JZS $no_emc ; no -> no EMC87
MOV DH, ndp_emc87 ; set NDP type to EMC87
JMPS $ndp_exit ; done
$no_emc: ADD DH,ndp_82S87-ndp_i80287; set old Cyrix types
FLD1 ; load 1.0
FLD ST(0) ; load another 1.0
FYL2XP1 ; compute 1.0*ld(2.0)
FLD1 ; compare result with 1.0
FCOMPP ; new Cyrix copros have correct result
FNSTSW AX ; store coprocessor condition bits
SAHF ; transfer to CPU flags
JNES $ndp_exit ; if incorrect result, not new Cyrix
ADD DH,ndp_82S87p-ndp_82S87; set NDP-type to new Cyrix types
JMPS $ndp_exit ; done
$chk_ct: CMP DL, cpu_i386 ; CPU >= 386 ?
JBS $chk_387DX ; no, can not be C&T
FNINIT ; initialize coprocessor
FLDPI ; load pi
F2XM1 ; 2**(pi)-1=pi/2, argument out of range
FLD1 ; load 1.0
FCHS ; -1.0
FLDPI ; load pi
FSCALE ; pi/2
FSTP ST(1) ; pi/2
FCOMPP ; 2**(pi)-1=pi/2 ?
FSTSW AX ; save condition codes
SAHF ; transfer to CPU flags
JNES $chk_387DX ; not equal, not C&T
ADD DH,ndp_38700-ndp_i387; set C&T types
JMPS $ndp_exit ; done
$chk_387DX: CMP DH, ndp_i387 ; Intel 387 ?
JNES $ndp_exit ; no, done. Only want to check i387
FNINIT ; initialize coprocessor
FLD1 ; load 1.0
FCHS ; -1.0
FXTRACT ; split into mantissa and exponent(0)
FSTP ST(0) ; pop mantissa
FXAM ; look at sign of exponent
FNSTSW AX ; store status word
AND AH, 2 ; C1 set (negative) on old 387
FSTP ST(0) ; clear coprocessor stack
JNZS $ndp_exit ; C1 set, no 387DX
MOV DH, ndp_i387DX ; set NDP-type to 387DX
FNINIT ; initialize coprocessor
FBSTP TBYTE PTR [GDT] ; store BCD indefinite
CMP BYTE PTR [GDT+7],0C0h; RapidCAD stores C0h, 387DX stores 80h
JNES $ndp_exit ; no RapidCAD
MOV DX, ndp_RapidCAD*100H+cpu_RapidCAD; RapidCAD (NDP=21,CPU=14)
$ndp_exit: LDS SI, ResultPtr ; pointer to result record
MOV [SI], DX ; save CPU and NDP types
JMPS $moveeven ; skip over test data for NDP check
$denormal DT 1
$nan DB 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 07Fh
$op1 DB 0F0h, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 03Fh
$53bit_prec DW 027Fh
$moveeven: CMP WORD PTR Debug_Flag,0; debugging output desired ?
JNZS $moveeven1 ; no
MOV AH, 9 ; #9, print string
PUSH CS ; load
POP DS ; address of
MOV DX, OFFSET CS:$dbg3 ; debugging message
INT 21h ; call DOS, print debugging message
JMPS $moveeven1 ; skip message text
$dbg3 DB 'About to perform MOVEEVEN memory speed test', 0Dh, 0Ah ,'$'
$moveeven1: MOV AX, DS ; set up segment registers
MOV ES, AX ; for memory move
XOR SI, SI ; offset in both segments
MOV DI, SI ; is zero
MOV CX, 5000 ; move 5000
REP MOVSW ; words
STRT_TIM ; start timer 2
XOR SI, SI ; offset in both segments
MOV DI, SI ; is zero
MOV CX, 5000 ; move 5000
REP MOVSW ; words
STOP_TIM ; elapsed time of timer 2 in BX
LDS SI, ResultPtr ; pointer to result record
MOV [SI+6], BX ; save MoveEvenTime
$movebyte: CMP WORD PTR Debug_Flag,0; debugging output desired ?
JNZS $movebyte1 ; no
MOV AH, 9 ; #9, print string
PUSH CS ; load
POP DS ; address of
MOV DX, OFFSET CS:$dbg5 ; debugging message
INT 21h ; call DOS, print debugging message
JMPS $movebyte1 ; skip message text
$dbg5 DB 'About to perform MOVEBYTE wait state test', 0Dh, 0Ah ,'$'
$movebyte1: MOV AX, DS ; set up segment registers
MOV ES, AX ; for memory move
MOV SI, 1 ; offset in source and destination
MOV DI, SI ; segment is odd
STRT_TIM ; start timer 2
MOV CX, 5000 ; move 5000
REP MOVSB ; bytes
STOP_TIM ; elapsed time of timer 2 in BX
LDS SI, ResultPtr ; pointer to result struct
MOV [SI+10], BX ; save MoveByteTime
$movedouble:CMP WORD PTR Debug_Flag,0; debugging output desired ?
JNZS $movedoubl1 ; no
MOV AH, 9 ; #9, print string
PUSH CS ; load
POP DS ; address of
MOV DX, OFFSET CS:$dbg6 ; debugging message
INT 21h ; call DOS, print debugging message
JMPS $movedoubl1 ; skip message text
$dbg6 DB 'About to perform MOVEDOUBLE 386sx test', 0Dh, 0Ah ,'$'
$movedoubl1:LDS SI, ResultPtr ; pointer to result struct
CMP BYTE PTR [SI],cpu_i386; CPU = iAPX 386 or i486 ?
JBS $move_ems ; no 386/486
MOV AX, DS ; load segment registers
MOV ES, AX ; for memory move
XOR SI, SI ; offset in source and destination
MOV DI, SI ; segment is 0
MOV CX, 5000 ; move 5000
REP MOVSD ; double words
STRT_TIM ; start timer 2
XOR SI, SI ; offset in source and destination
MOV DI, SI ; segment is 0
MOV CX, 5000 ; move 5000
REP MOVSD ; double words
STOP_TIM ; elapsed time for 2 in BX
LDS SI, ResultPtr ; pointer to result struct
MOV [SI+24], BX ; save MoveDouble-Time
$chk_386sx: CMP BYTE PTR [SI], cpu_i486 ; CPU >= i486 ?
JAES $move_ems ; yes, no need to test for 386sx
MOV AX, [SI+6] ; AX = MoveWord-Time
XCHG AX, BX ; AX = MoveDouble-Time,BX=MoveWord-Time
SUB AX, BX ; MoveDTime - MoveWTime
ADD AX, AX ; 2 * (MoveDTime - MoveWTime)
CWD ; compute
XOR AX, DX ; Abs (2 * (MoveDoubleTime -
SUB AX, DX ; MoveWordTime))
CMP BX, AX ; Abs(2*(MoveDTime-MoveWTime))>MoveWTime ?
ADC WORD PTR [SI], 0 ; CPU type = 386sx if true
CMP BYTE PTR [SI],cpu_ct38600sx; CPU = C&T 38600sx ?
JNES $move_ems ; no
MOV BYTE PTR [SI],cpu_i386sx; POPAD test unreliable for 386sx,
; reset to Intel 386 since more likely
$move_ems: CMP WORD PTR Debug_Flag,0; debugging output desired ?
JNZS $move_ems1 ; no
MOV AH, 9 ; #9, print string
PUSH CS ; load
POP DS ; address of
MOV DX, OFFSET CS:$dbg7 ; debugging message
INT 21h ; call DOS, print debugging message
JMPS $move_ems1 ; skip message text
$dbg7 DB 'About to perform EMS memory access test', 0Dh, 0Ah ,'$'
$move_ems1: CMP BYTE PTR EMS_Flag, 0 ; does EMS memory exist ?
JES $move_ext ; no, skip this test
MOV AH, 43h ; #43, allocate page
MOV BX, 1 ; one page
INT 67h ; call EMM-driver (handle in DX)
MOV AH, 47h ; #47, save page map
INT 67h ; call EMM-driver
MOV AH, 44h ; #44, map page
MOV AL, 0 ; physical page 0
MOV BX, 0 ; logical page 0
INT 67h ; call EMM-driver
LES DI, BufferPtr ; pointer to buffer
MOV CX, 5000 ; 5000 words
LDS SI, ResultPtr ; pointer to result struct
STRT_TIM ; start timer 2
CMP BYTE PTR [SI], cpu_i386 ; processor 386 or higher?
LDS SI, EMS_Base ; pointer to EMS page frame
JAES $is_386 ; is a 386/486
REP MOVSW ; move words from page frame to buffer
JMPS $no_386 ; was no 386/486
$is_386: MOV CX, 4000 ; 4000 double words = 1 EMS page
REP MOVSD ; move 4000 double words
$no_386: STOP_TIM ; elapsed time of timer 2 in BX
LDS SI, ResultPtr ; pointer to result struct
MOV [SI+12], BX ; save MoveEMSTime
MOV AH, 48h ; #48, restore map
INT 67h ; call EMM-driver
MOV AH, 45h ; #45, deallocate page
INT 67h ; call EMM-driver
$move_ext: CMP WORD PTR Debug_Flag,0; debugging output desired ?
JNZS $move_ext1 ; no
MOV AH, 9 ; #9, print string
PUSH CS ; load
POP DS ; address of
MOV DX, OFFSET CS:$dbg8 ; debugging message
INT 21h ; call DOS, print debugging output
JMPS $move_ext1 ; skip message text
$dbg8 DB 'About to perform extended memory access test', 0Dh, 0Ah ,'$'
$move_ext1: CMP BYTE PTR Ext_Flag, 0 ; does extended memory exist ?
JES $screenfill ; no, skip test
STRT_TIM ; start timer 2
XOR AX, AX ; load zero
MOV BX, SS ; load
MOV ES, BX ; address
LEA DI, GDT ; of GDT
MOV CX, 30h ; 30h bytes long
REP STOSB ; init with 0
LEA SI, GDT ; reload address of GDT
MOV WORD PTR GDT+10H,10000; number of bytes to move
MOV WORD PTR GDT+12H, 0 ; source:
MOV BYTE PTR GDT+14H, 10H; 100000H (start of extended memory)
MOV BYTE PTR GDT+15H, 93H; access rights (read/write)
MOV WORD PTR GDT+18H,10000; number of bytes to move
LDS DI, BufferPtr ; load pointer to buffer
MOV AX, DS ; load pointer into DX:AX
XOR DX, DX ; linearize
SHL AX, 1 ; address,
RCL DX, 1 ; 32 bit result
SHL AX, 1 ; in
RCL DX, 1 ; DX:AX
SHL AX, 1 ;
RCL DX, 1 ;
SHL AX, 1 ;
RCL DX, 1 ;
ADD AX, DI ;
ADC DX, 0 ;
MOV WORD PTR GDT+1AH, AX ; destination:
MOV BYTE PTR GDT+1CH, DL ; buffer
MOV BYTE PTR GDT+1DH, 93H; access rights (read/write)
MOV AH, 87h ; move from extended memory
MOV CX, 5000 ; move 5000 words from ext to buffer
INT 15H ; call AT-BIOS
STOP_TIM ; elapsed time of timer 2 in BX
LDS SI, ResultPtr ; pointer to result record
MOV [SI+14], BX ; save MoveExtTime
$screenfill:CMP WORD PTR Debug_Flag,0; debugging output desired ?
JNZS $screenfil1 ; no
MOV AH, 9 ; #9, print string
PUSH CS ; load
POP DS ; address of
MOV DX, OFFSET CS:$dbg9 ; debugging message
INT 21h ; call DOS, print string
JMPS $screenfil1 ; skip message text
$dbg9 DB 'About to perform SCREENFILL test', 0Dh, 0Ah ,'$'
$screenfil1:LES DI, ScreenPtr ; pointer to start of video memory
STRT_TIM ; start timer 2
MOV CX, 5000 ; fill 5000 bytes
REP STOSB ; of video memory
STOP_TIM ; elapsed time for timer 2 in BX
LDS SI, ResultPtr ; pointer to result struct
MOV [SI+16], BX ; save ScreenFillTime
$bios_write:CMP WORD PTR Debug_Flag,0; debugging output desired ?
JNZS $bios_writ1 ; no
MOV AH, 9 ; #9, print string
PUSH CS ; load
POP DS ; address of
MOV DX, OFFSET CS:$dbg4 ; debugging message
INT 21h ; call DOS, print debugging message
JMPS $bios_writ1 ; skip message text
$dbg4 DB 'About to perform BIOS_WRITE screen speed test', 0Dh, 0Ah ,'$'
$bios_writ1:STRT_TIM ; start timer 2
MOV SI, 20 ; write 20 characters
$out_loop: MOV AX, 0920h ; #9, write char and attribute
MOV BX, 0 ; page 0, attribute = blank
MOV CX, 1 ; write one character at a time
INT 10H ; call video-BIOS
DEC SI ; loop over number of chars
JNZS $out_loop ; until all 20 chars output
STOP_TIM ; elapsed time of timer 2 in BX
LDS SI, ResultPtr ; pointer to result struct
MOV [SI+8], BX ; save BIOS-WriteTime
$speed87: CMP WORD PTR Debug_Flag,0; debugging output desired ?
JNZS $speed871 ; no
MOV AH, 9 ; #9, print string
PUSH CS ; load
POP DS ; address of
MOV DX, OFFSET CS:$dbg10 ; debugging message
INT 21h ; call DOS, print debugging message
JMPS $speed871 ; skip message text
$dbg10 DB 'About to perform NDP speed test', 0Dh, 0Ah ,'$'
$speed871: LDS SI, ResultPtr ; pointer to result struct
CMP BYTE PTR [SI+1], 1 ; real coprocessor present ?
JAS $cont_87 ; yes, do coprocessor tests
JMP $no_fpu ; no, done
$cont_87: WAIT ; for 8087
FNINIT ; initialize coprocessor
WAIT ; for 8087
FLD1 ; load 1
STRT_TIM ; start timer 2
REPT 40 ; do following 40 times:
WAIT ; needed on 8087
FSQRT ; compute Sqrt(1)
ENDM
FWAIT ; wait until coprocessor done
STOP_TIM ; time for 40 sqrt computations on BX
LDS SI, ResultPtr ; pointer to result struct
MOV [SI+20], BX ; save 87-Time
$speed287: FNINIT ; initialize coprocessor
FLD1 ; load 1
STRT_TIM ; start timer 2
REPT 40 ; do following 40 times:
NOP ; needed on 8087
FSQRT ; compute Sqrt(1)
ENDM
STOP_TIM ; time for 40 sqrt computations in BX
LDS SI, ResultPtr ; pointer to result struct
MOV [i287Time], BX ; save 287-Time
MOV CX, [SI] ; get CPU (CL) and NDP (CH)
$chk_387sx: CMP CL, cpu_i386sx ; CPU = 80386sx ?
JES $has_387sx ; is SX
CMP CL, cpu_ct38600sx ; CPU = 38600sx ?
JES $has_387sx ; is SX
CMP CL, cpu_486slc ; CPU = 486SLC ?
JNES $no_387sx ; no SX
$has_387sx: INC CH ; set SX versions of 387 coprocessors
$no_387sx:
$store_type:MOV [SI], CX ; save CPU and NDP type
CMP CL, cpu_i286 ; CPU higher than 286 ?
JBES $no_weitek ; no, Weitek only available for 386/486
PUSH SI ; save pointer
PUSH DS ; to result struct
XOR EAX, EAX ; zero everything in result register
INT 11h ; do equipment check
TEST EAX, 01000000h ; check bit 24, set if Weitek present
POP DS ; restore pointer
POP SI ; to result struct
JES $no_weitek ; bit not set, no Weitek
OR BYTE PTR [SI+1], 80h ; set Weitek flag in coprocessor type
$no_weitek: FNINIT ; reprogram
FLDCW [SaveCtrl] ; original NDP control word
$no_fpu: MOV AL, [SystemStat] ; get original system status
OUT 61h, AL ; and restore it
$ende: POPF ; restore original flag settings
POP DS ; restore Turbo Pascal's data segment
MOV SP, BP ; discard local variables
POP BP ; restore caller's frame pointer
RET 22 ; return, pop parameters
COMMENT #
MOV EAX, 0417A000h ; test if early 80386
MOV ECX, 00000081h ; processor with 32 multiplication bug
MUL ECX
CMP EDX, 00000002h
JNZS $mul_err
CMP EAX, 0FE7A000h
JNZS $mul_err
#
SpeedTest ENDP
CODE ENDS
END